﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;

namespace SageKing.Core.Extensions;

public static class IServiceCollectionExts
{
    /// <summary>
    /// 自动注册服务
    /// IScopedService
    /// ITransientService
    /// ISingletonService
    /// </summary>
    /// <param name="services"></param>
    /// <param name="assembly"></param>
    public static void AddAutoRegisteredServices(this IServiceCollection services, Assembly assembly)
    {
        var types = assembly.GetExportedTypes()
            .Where(t => t.IsClass && !t.IsAbstract);

        foreach (var implType in types)
        {
            try
            {
                var interfaces = implType.GetInterfaces();
                // 查找实现了标记接口的那个服务接口
                var serviceType = interfaces.FirstOrDefault(i =>
                    AutoServiceConst.getScopedType.IsAssignableFrom(i) ||
                    AutoServiceConst.getTransientType.IsAssignableFrom(i) ||
                    AutoServiceConst.getSingletonType.IsAssignableFrom(i));

                if (serviceType == null) continue;

                //如果直接继承了标记接口，直接注册服务
                if (serviceType == AutoServiceConst.getScopedType)
                    services.AddScoped(implType);
                else if (serviceType == AutoServiceConst.getTransientType)
                    services.AddTransient(implType);
                else if (serviceType == AutoServiceConst.getSingletonType)
                    services.AddSingleton(implType);
                else
                {
                    // 根据标记接口确定生命周期
                    if (typeof(ISingletonService).IsAssignableFrom(serviceType))
                        services.AddSingleton(serviceType, implType);
                    else if (typeof(IScopedService).IsAssignableFrom(serviceType))
                        services.AddScoped(serviceType, implType);
                    else if (typeof(ITransientService).IsAssignableFrom(serviceType))
                        services.AddTransient(serviceType, implType);

                }

            }
            catch (Exception ex)
            {
                Console.Error.WriteLine($"自动注册服务出错：{implType.FullName}\n{ex}");
            }
        }
    }
}
